package com.atwulidun.interpreter19;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;

public class Calculator {
    // 将传进来的表达式(譬如a+b-c+d)一通解析后最后应该是会得到一个AddExpression或者SubExpression类型的Expression对象
    private Expression expression;


    public Calculator(String expString) {
        getExpression(expString);
    }

    // 对传进来的字符串进行解析并获取Expression对象的方法
    private void getExpression(String expString) {
        // 创建一个栈
        Deque<Expression> stack = new ArrayDeque<>();
        // 将expString转换成字符数组后再进行解析
        char[] chars = expString.toCharArray();
        Expression left = null;
        Expression right = null;
        for (int i = 0; i < chars.length; i++) {
            switch (chars[i]) {
                case '+':
                    // 从stack中获取左表达式
                    left = stack.pop();
                    // 获取右表达式，应该为一个VarExpression对象，注意：这里使用++i，下次再进循环就是从右边变量右边的操作符开始
                    right = new VarExpression(String.valueOf(chars[++i]));
                    // 再创建一个AddExpression对象，并接入到stack中
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    // 从stack中获取左表达式
                    left = stack.pop();
                    // 获取右表达式，应该为一个VarExpression对象
                    right = new VarExpression(String.valueOf(chars[++i]));
                    // 再创建一个AddExpression对象，并接入到stack中
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    // 扫描到的是变量，创建对应的VarExpression对象并将其放到stack中，按理只有第一个变量会走到这里
                    stack.push(new VarExpression(String.valueOf(chars[i])));
                    break;
            }
        }
        // 表达式扫描完成，保存最后得到的Expression对象，注意：只有一个！
        expression = stack.pop();
    }

    // 根据扫描完成得到的Expression对象来计算表达式结果的方法
    public int calculate(Map<String, Integer> var) {
        return expression.interpret(var);
    }
}
